import { useHttpErrorHandler } from "@/hooks";
import type { InjectionKey } from "vue";
import { createStore, Store as VStore, useStore as baseUseStore } from "vuex";

export interface ResponseProps<T = Record<string, never>> {
  code: number;
  msg?: string;
  data?: T;
  error?: string;
}
export interface UserProps {
  username?: string;
  email?: string;
  name?: string;
  id?: string;
}
export interface ImageProps {
  id?: string;
  url?: string;
  createdAt?: string;
}
export interface ColumnProps {
  id: string;
  title: string;
  avatar?: {
    url?: string;
    id?: string;
    createdAt?: string;
  };
  description: string;
}

export interface State {
  user: UserProps;
  columnLists: ColumnProps[];
  columnsTotal: number;
  isLogin: boolean;
}
export const injectStoreKey: InjectionKey<VStore<State>> = Symbol();

const Store = createStore<State>({
  state: {
    isLogin: !!sessionStorage.getItem("token"),
    user: {},
    columnLists: [],
    columnsTotal: 0,
  },
  mutations: {
    setIsLogin(state, payload: boolean) {
      state.isLogin = payload;
    },
    setCurrentUser(state, payload: UserProps) {
      state.user = payload;
    },
    updateColumnLists(state, payload = []) {
      state.columnLists = [...state.columnLists, ...payload];
    },
    updateColumnsTotal(state, payload = 0) {
      state.columnsTotal = payload;
    },
    setToken(state, payload) {
      sessionStorage.setItem("token", payload);
    },
    logout() {
      sessionStorage.removeItem("token");
    },
  },
  actions: {
    async login({ commit }, payload) {
      try {
        const res: ResponseProps = await fetch("/api/login", {
          method: "post",
          body: JSON.stringify(payload),
          headers: {
            "Content-Type": "application/json",
          },
        }).then((res) => res.json());
        commit("setToken", res.data?.token);
        commit("setCurrentUser", res.data?.user ?? {});
        commit("setIsLogin", true);

        return res.data;
      } catch (error) {}
    },
    async logout({ commit }) {
      try {
        const token = sessionStorage.getItem("token");
        await fetch("/api/logout", {
          method: "post",
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }).then((r) => r.json());
        commit("logout");
        commit("setCurrentUser", {});
        commit("setIsLogin", false);
      } catch (error) {}
    },
    async getCurrentUser({ commit }, payload) {
      const { handleError, handleResponse } = useHttpErrorHandler(
        payload.router,
        commit
      );

      try {
        const token = sessionStorage.getItem("token");
        const res = await fetch("/api/user", {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }).then((res) => handleResponse(res));
        commit("setCurrentUser", res.data);
      } catch (error) {
        handleError(error as HttpError);
      }
    },
    async getColumns(context, payload) {
      const { router, ...restPayload } = payload;
      const { handleError, handleResponse } = useHttpErrorHandler(
        router,
        context.commit
      );
      try {
        const pathParamStr = new URLSearchParams(restPayload).toString();
        const token = sessionStorage.getItem("token");
        const res = await fetch(`/api/courses?${pathParamStr}`, {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }).then((res) => handleResponse(res));
        context.commit("updateColumnLists", res.data?.list ?? []);
        context.commit("updateColumnsTotal", res.data?.total ?? 0);
      } catch (error) {
        handleError(error as HttpError);
      }
    },
  },
});

export default Store;

// 定义自己的 `useStore` 组合式函数
export function useStore(): VStore<State> {
  return baseUseStore(injectStoreKey);
}
